/*
	bassfce.cpp

	Copyright (c) 2009 by Lms <lms.cze7@gmail.com>

 ***************************************************************************
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 ***************************************************************************
*/

#include "bassfce.h"
#include "general.h"

BASSThread bt;
HSTREAM chan;

QString info_stream;
QString info_radio;
QString info_song;
QString info_bitrate;
QString info_url;

QHash<QString,BASSPluginInfo*> m_bass_plugins;

void BASSMSG(int index, QString text, int number)
{
	switch( index )
	{
		case 0:		// Connecting

			break;
		case 1:		// Can't play the stream  (Not playing)

			break;
		case 2:		// Buffering

			break;
		case 3:		// Radio
			qDebug() << "[FMtune]"<<"Radio:"<<text;
			info_radio = text;
			break;
		case 4:		//Bitrate
		case 5:		//-- Bitrate
		case 6:		//-- Bitrate
			info_bitrate = text;
			break;
		case 7:		// Song
			qDebug() << "[FMtune]"<<"Song:"<<text;
			info_song = text;
			break;
		case 8:		//icy info - Bitrate
			info_bitrate = text;
			break;
		case 201:		//icy - url
			if (text != "") {
				info_url = text;
			}
			break;
		default :
			break;
	}

}

void DoMeta()
{
	const char *meta=BASS_ChannelGetTags(chan,BASS_TAG_META);
	if (meta) { // got Shoutcast metadata		
		char *p=strstr((char*)meta,"StreamTitle='");
		if (p) {
			p=strdup(p+13);
			strchr(p,';')[-1]=0;
			qDebug()<<"song not decode - "<<p;
			//BASSMSG(7, p, 0);
			BASSMSG(7, QString().fromUtf8(p), 0);
			//BASSMSG(7, QString().fromUtf16(p), 0);
			free(p);
		}
	} else {		
		meta=BASS_ChannelGetTags(chan,BASS_TAG_OGG);
		if (meta) { // got Icecast/OGG tags
			const char *artist=NULL,*title=NULL,*p=meta;
			for (;*p;p+=strlen(p)+1) {
				if (!qstrnicmp(p,"artist=",7)) // found the artist
					artist=p+7;
				if (!qstrnicmp(p,"title=",6)) // found the title
					title=p+6;
			}
			if (artist) {
				BASSMSG(7, QString("%1 - %2").arg(QString().fromUtf8(artist), QString().fromUtf8(title)), 0);
			} else if (title) {
				BASSMSG(7, QString().fromUtf8(title), 0);
			}
		}
    }
}

void CALLBACK MetaSync(HSYNC handle, DWORD channel, DWORD data, void *user)
{
	DoMeta();
}

void CALLBACK EndSync(HSYNC handle, DWORD channel, DWORD data, void *user)
{
	BASSMSG(0, "not playing", 0);
}

void CALLBACK StatusProc(const void *buffer, DWORD length, void *user)
{
	if (buffer && !length){
	//	MESS(32,WM_SETTEXT,0,buffer); // display connection status
	
	QList<QVariant> list;

/*	list.clear();
	list.append("     ");
	list.append(QString("<b>%1</b>").arg(buffer));*/
	//fmtunePlugin
	//emit fmtunePlugin::fmtunePluginSystem()->setContactItemRow(cntfmtune, list, 1);
	//fmtunePS

////	emit fmtunePS->setContactItemRow(cntfmtune, list, 1);
	}

}

QString BASSGetInfoSong()
{
	return info_song;
}

QString BASSGetInfoRadio()
{
	return info_radio;
}

QString BASSGetInfoBitrate()
{
	return info_bitrate;
}

QString BASSGetInfoURL()
{
	return info_url;
}

int BASSGetPluginsCount()
{
	return m_bass_plugins.size();
}

QString BASSGetPluginName(int id)
{
	BASSPluginInfo *plginfo = m_bass_plugins.value(QString("%1").arg(id));
	return plginfo->m_name+"  ("+plginfo->m_exts+")";
}

void LoadBASS()
{
	qDebug() << "start LoadBASS";

	chan = 0;

	int bassFlags;
	bassFlags=0;

	// check the correct BASS was loaded
	if (HIWORD(BASS_GetVersion())!=BASSVERSION) {
		qDebug() << "[FMtune]" << "An incorrect version of BASS was loaded.";
		QMessageBox msgBox;
		msgBox.setText(QMessageBox::tr("An incorrect version of BASS was loaded."));
		int ret = msgBox.exec();
	}

	QSettings settings(QSettings::defaultFormat(),QSettings::SystemScope, SystemsCity::PluginSystem()->getProfilePath(), "fmtune");
	int currdev=settings.value("devices/current", "0").toInt();
	qDebug()<<"Current device" << currdev;
	if (currdev==0) {
		currdev=-1;
		qDebug()<<"Current device - changed on " << currdev;
	}

	#ifdef __linux__
	int useDMIX=settings.value("devices/dmix", "0").toInt();
	if (useDMIX==1){	//enabled
		bassFlags += BASS_DEVICE_DMIX;	// use "dmix" (shared) output
	}
	#endif

	// setup output device
	if (!BASS_Init(currdev, 44100, bassFlags, NULL, NULL)) {
		qDebug() << "[FMtune]" << "Can't initialize device";
		QMessageBox msgBox;
		msgBox.setText(QMessageBox::tr("Can't initialize device"));
		int ret = msgBox.exec();
	}

	BASS_SetConfig(BASS_CONFIG_NET_PLAYLIST,1); // enable playlist processing
	BASS_SetConfig(BASS_CONFIG_NET_PREBUF,0); // minimize automatic pre-buffering, so we can do it (and display it) instead
//	BASS_SetConfigPtr(BASS_CONFIG_NET_PROXY,proxy); // setup proxy server location

	/*if Proxy_Mode in [1, 2] then
	BASS_SetConfigPtr(BASS_CONFIG_NET_PROXY, @proxy[0]) // setup proxy server location
	else*/
	BASS_SetConfigPtr(BASS_CONFIG_NET_PROXY, NULL); // no proxy!


	// Load plugins		
	QStringList pluginsPaths;
	QString pluginPath;

	QDir pluginDir;
	QStringList files;

	m_bass_plugins.clear();
	pluginsPaths = getQutIMPluginsPaths();

	foreach(const QString &path, pluginsPaths) {
		pluginPath = path+"/fmtune/plugins";
		qDebug() << "[FMtune]" << "Search BASS plugins at: " << pluginPath;

		pluginDir = QDir(pluginPath);

		files.clear();
		files = pluginDir.entryList(QStringList("*.*"), QDir::Files | QDir::NoSymLinks);

		for (int i = 0; i < files.size(); ++i) {
			qDebug() << files[i];
			HPLUGIN plug;
			QString plgpth = pluginPath+"/"+files[i];

			if (plug=BASS_PluginLoad( QDir().relativeFilePath(plgpth).toLatin1() , 0)) { // plugin loaded...
				qDebug() << files[i] << "LOADED";

				const BASS_PLUGININFO *pinfo=BASS_PluginGetInfo(plug); // get plugin info to add to the file selector filter...

				for (int a=0;a<pinfo->formatc;a++) {
					qDebug() << pinfo->formats[a].name << pinfo->formats[a].exts;

					BASSPluginInfo *plginfo = new BASSPluginInfo;
					plginfo->m_file_name = files[i];
					plginfo->m_loaded	 = true;
					plginfo->m_name		 = pinfo->formats[a].name;
					plginfo->m_exts		 = pinfo->formats[a].exts;

					m_bass_plugins.insert(QString("%1").arg(m_bass_plugins.count()), plginfo);
				}
			}

		}

	}
	qDebug() << "finish LoadBASS";
}

void BASSSetVolume(int value)
{
	DWORD v = /*round(*/value * (10000 / 100)/*)*/ ;

	BASS_SetConfig(BASS_CONFIG_GVOL_MUSIC, v );
	BASS_SetConfig(BASS_CONFIG_GVOL_STREAM, v );
}

bool BASSIsPlaying()
{
	if (chan!=0){
		return true;
	}
	else {
		return false;
	}
}

void BASSStop()
{
	BASS_StreamFree(chan);
	chan=0;
}

void BASSPlay(QString streamurl)
{
	qDebug() << "[FMtune]" << "BASSPlay" << streamurl;

	DWORD len;
	DWORD progress;
	QList<QVariant> list;

	BASS_StreamFree(chan); // close old stream
	chan=0;
	qDebug() << "[FMtune]" << "BASSPlay" << "FREE";

	info_url = streamurl;

	chan=BASS_StreamCreateURL(streamurl.toLatin1(),0,BASS_STREAM_BLOCK|BASS_STREAM_STATUS|BASS_STREAM_AUTOFREE,StatusProc,0); // open URL
	qDebug() << "[FMtune]" << "BASSPlay" << "StreamCreateURL";

	if (!chan) { // failed to open
		qDebug() << "[FMtune]" << "BASSPlay" << "failed to open";

		BASSMSG(0, "not playing", 0);

		QMessageBox msgBox;
		msgBox.setText("Can't play the stream");
		int ret = msgBox.exec();
	} else {
		qDebug() << "[FMtune]" << "BASSPlay" << "open ok";	

/*			// nekdy nefunguje !!!!!!!!!!!!!!!!!!
		progress= 0;
		while(progress < 75)
		{
			len = BASS_StreamGetFilePosition(chan, BASS_FILEPOS_END);
			if (len ==  -1 ) {
				//break; // something's gone wrong! (eg. BASS_Free called)
			}	

			progress = (BASS_StreamGetFilePosition(chan, BASS_FILEPOS_DOWNLOAD) -
			BASS_StreamGetFilePosition(chan, BASS_FILEPOS_CURRENT)) * 100  / len;
			// percentage of buffer filled
			// SendMessage(win, WM_INFO_UPDATE, 2, progress); // show the Progess value in the label
		

			list.clear();
			list.append("     ");
			list.append(QString("<b>buffering... %1</b>").arg(progress));

			////	emit fmtunePluginSystem->setContactItemRow(cntfmtune, list, 1);

		}//while
*/

		list.clear();
		list.append("     ");
		list.append(QString("<b>Playing?... %1</b>"));

		////	emit fmtunePluginSystem->setContactItemRow(cntfmtune, list, 1);


		qDebug() << "[FMtune]" << "BASSPlay" << "fces";

		// get the stream title and set sync for subsequent titles
		DoMeta();
		BASS_ChannelSetSync(chan,BASS_SYNC_META,0,&MetaSync,0); // Shoutcast
		BASS_ChannelSetSync(chan,BASS_SYNC_OGG_CHANGE,0,&MetaSync,0); // Icecast/OGG
		// set sync for end of stream
		BASS_ChannelSetSync(chan,BASS_SYNC_END,0,&EndSync,0);

		// play it!
		qDebug() << "[FMtune]" << "BASSPlay" << "ChannelPlay";
		BASS_ChannelPlay(chan, FALSE);	

		qDebug() << "[FMtune]" << "BASSPlay" << "checking icy tag";
		const char *icy=BASS_ChannelGetTags(chan,BASS_TAG_ICY);

		if (!icy) icy=BASS_ChannelGetTags(chan,BASS_TAG_HTTP); // no ICY tags, try HTTP
		if (icy) {
			for (;*icy;icy+=strlen(icy)+1) {
				//	qstrncasecmp

				if (!qstrnicmp(icy,"icy-name:",9)) {
					BASSMSG(3, icy+9, 0);
					qDebug()<<"icy-name"<<icy+9;
				}
				if (!qstrnicmp(icy,"icy-url:",8)) {
					BASSMSG(201, icy+8, 0);
					qDebug()<<"icy-url"<<icy+8;
				}
				if (!qstrnicmp(icy,"icy-br:",7)) {
					BASSMSG(4, icy+7, 0);
					qDebug()<<"icy-br"<<icy+7;
				}
			}
		}
		qDebug() << "[FMtune]" << "BASSPlay" << "checked icy tag";

	}
}

void BASSThread::run()
{

}

QStringList getQutIMPluginsPaths()
{
	// --- copied from qutIM - trunk/src/pluginsystem.cpp ---

	QSettings settings(QSettings::IniFormat, QSettings::UserScope, "qutim", "qutimsettings");

	QStringList paths;
	QDir root_dir = QApplication::applicationDirPath();
	// 1. Windows, ./plugins
	QString plugin_path = root_dir.canonicalPath();
	plugin_path += QDir::separator();
	plugin_path += "plugins";
	paths << plugin_path;
	root_dir.cdUp();
	// 2. Linux, /usr/lib/qutim
	// May be it should be changed to /usr/lib/qutim/plugins ?..
	plugin_path = root_dir.canonicalPath();
	plugin_path += QDir::separator();
	plugin_path += "lib";
	plugin_path += QDir::separator();
	plugin_path += "qutim";
	paths << plugin_path;
	plugin_path += QDir::separator();
	plugin_path += "plugins";
	paths << plugin_path;
	// 3. MacOS X, ../PlugIns
	plugin_path = root_dir.canonicalPath();
	plugin_path += QDir::separator();
	plugin_path += "PlugIns";
	paths << plugin_path;
	// 4. Safe way, ~/.config/qutim/plugins
	plugin_path = QFileInfo(settings.fileName()).canonicalPath();
	plugin_path += QDir::separator();
	plugin_path += "plugins";
	paths << plugin_path;
	// 5. From config
	QStringList config_paths = settings.value("General/libpaths", QStringList()).toStringList();
	while(config_paths.size())
		paths << config_paths.takeFirst();

	//qDebug() << "[FMtune]" << paths;
	return paths;
}
